package com.smarthospital.service.impl;

import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.smarthospital.common.util.SHDateUtil;
import com.smarthospital.dao.daoService.*;
import com.smarthospital.entity.dto.DutiesDTO;
import com.smarthospital.entity.pojo.Doctor;
import com.smarthospital.entity.pojo.DoctorDuty;
import com.smarthospital.entity.pojo.InquiryOrder;
import com.smarthospital.entity.pojo.User;
import com.smarthospital.service.DoctorService;
import com.smarthospital.service.SHDictionaryService;
import com.smarthospital.web.inteceptor.LoginInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * create by sym  2021/5/29 17:41.
 */
@Service
@Slf4j
public class DoctorServiceImpl implements DoctorService {

    @Autowired
    private InquiryOrderDaoService inquiryOrderDaoService;
    @Autowired
    private DoctorDaoService doctorDaoService;
    @Autowired
    private DoctorDutyDaoService doctorDutyDaoService;

    @Autowired
    private SHDictionaryService dictionaryService;

    @Override
    public PageInfo<Doctor> querDoctors(Integer doctorLevel, Integer pageSize, Integer pageNum) throws ParseException {
        User user = LoginInterceptor.getUser();

        PageInfo<Doctor> pageInfo = doctorDaoService.querDoctors(doctorLevel, pageSize, pageNum);
        List<Doctor> list = pageInfo.getList();
        List<Long> doIds = new ArrayList<>(list.size());
        list.stream().mapToLong(Doctor::getId).forEach(doIds::add);
        //优化一次查询，根据医生分组
        List<InquiryOrder> allOrders = inquiryOrderDaoService.queryOrderWithDoIds(doIds);
        Map<Long, List<InquiryOrder>> listMap = allOrders.stream().filter(o->o.getDoctorLevel().equals(doctorLevel)).collect(Collectors.groupingBy(d -> d.getId()));
        //是否在忙  诊断次数
        for (Doctor doctor : list) {
            //该医生的付款成功就诊单
            List<InquiryOrder> orders = listMap.get(doctor.getId());
            if (CollectionUtils.isEmpty(orders)) {
                continue;
            }
            doctor.setTimes(orders.size());
            //当前的【电话/视频】就诊时间段 里有没有有效订单
            //当前时间的 就诊时间段排班
            String nowRangeTime = SHDateUtil.getRangeTime();
            boolean isBusy = orders.stream().filter(o->!o.getInquiryType().equals(0)).anyMatch(o -> o.getInquiryTime().equals(nowRangeTime));
            doctor.setIsBusy(isBusy?1:0);
            //当前用户是否预约
            List<InquiryOrder> collect = orders.stream().filter(o -> o.getInquiryManId().equals(user.getId())).filter(o -> o.getStatus().equals(1)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(collect)) {

                InquiryOrder order = collect.stream().min((o1, o2) -> SHDateUtil.compareRangeTime(o1.getInquiryTime(), o2.getInquiryTime())).orElse(null);
                doctor.setSubscribeStartTime(order!=null?order.getInquiryTime():"");
                String rangeEndTime = SHDateUtil.getRangeEndTime(order.getInquiryTime());
                doctor.setSubscribeEndTime( rangeEndTime);
                doctor.setIsSubscribe(SHDateUtil.isAfterRangeTime(rangeEndTime)?2:1);
            }

        }

        //查询是否存在0元下单白嫖资格，将这个医生置顶  这里也不需要去数据库查，直接解析所有医生相关订单
        list.sort(Comparator.comparing((d1)->{
            List<InquiryOrder> orders = listMap.get(d1.getId());
            if (null == orders) {
                orders = new ArrayList<>(0);
            }
            List<InquiryOrder> orderList = orders.stream().filter(d -> d.getInquiryManId().equals(user.getId()))
                    .collect(Collectors.toList());
            return  inquiryOrderDaoService.hasZeroFeeMethod(orderList)?1:0;  //todo 这里有点绕 需要测试
        }));
        //刚好预约的就往前放  todo test
        list.sort(Comparator.comparing(Doctor::getIsSubscribe));

        //将医生的字典字段处理下
        dictionaryService.resolveDoctorDictionFields(list);
        return pageInfo;
    }

    /**
     * 根据医生工号查询医生排班信息表
     * @param doctor
     * @return
     */
    @Override
    public List<DutiesDTO> doctorDuty(String doctor) {
        DoctorDuty doctorDuty = DoctorDuty.builder().status("0").doctor(doctor).build();
        List<DoctorDuty> list = doctorDutyDaoService.queryDuties(doctorDuty);
        //处理排班是否可预约
        Doctor doctorPo =  doctorDaoService.queryByDoctorStr(doctor);
        InquiryOrder order = InquiryOrder.builder().status(1).doctorId(doctorPo.getId()).build();
        List<InquiryOrder> orders = inquiryOrderDaoService.queryOrder(order);
        for (DoctorDuty duty : list) {
            String rangeTime = duty.getDate()+" " + duty.getTimeRange().split("-")[0];
            if (orders.stream().anyMatch(o->o.getInquiryTime().equals(rangeTime))) {
                duty.setSuscribable(1);
            }
        }
        //按一个星期的数据返回
        List<DutiesDTO> duties = buildAndSort(list);
        return duties;
    }

    @Override
    public List<DutiesDTO> duties(String major) {
        DoctorDuty doctorDuty = DoctorDuty.builder().status("0").build();
        List<DoctorDuty> list;
        List<InquiryOrder> orders;
        if (StringUtils.isEmpty(major)) {
            list = doctorDutyDaoService.queryDuties(doctorDuty);
            orders = inquiryOrderDaoService.queryOrder(InquiryOrder.builder().status(1).build());
        }else {
            list = doctorDutyDaoService.queryDutiesWithMajor(major);
            //按专业来分的需要连表查询
            orders = inquiryOrderDaoService.queryByMajor(major,1);
        }

        //处理排班是否可预约
        for (DoctorDuty duty : list) {
            String rangeTime = duty.getDate()+" " + duty.getTimeRange().split("-")[0];
            //医生匹配  时间相等
            if (orders.stream().anyMatch(o->o.getInquiryTime().equals(rangeTime)&&duty.getDoctor().equals(o.getDoctor()))) {
                duty.setSuscribable(1);
            }
        }
        return buildAndSort(list);
    }

    @Override
    public Doctor getDoctorById(Integer doctorId) throws ParseException {
        User user = LoginInterceptor.getUser();

        Doctor doctor = doctorDaoService.queryById(Long.valueOf(doctorId + ""));
        //是否在忙  诊断次数
        //该医生的付款成功就诊单
        List<InquiryOrder> orders = inquiryOrderDaoService.queryOrderWithDoIds(Lists.newArrayList(doctor.getId()));
        doctor.setTimes(orders.size());
        //当前的【电话/视频】就诊时间段 里有没有有效订单
        //当前时间的 就诊时间段排班
        String nowRangeTime = SHDateUtil.getRangeTime();
        boolean isBusy = orders.stream().filter(o->!o.getInquiryType().equals(0)).anyMatch(o -> o.getInquiryTime().equals(nowRangeTime));
        doctor.setIsBusy(isBusy?1:0);
        //当前用户是否预约  todo  test
        List<InquiryOrder> collect = orders.stream().filter(o -> o.getInquiryManId().equals(user.getId())).filter(o -> o.getStatus().equals(1)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(collect)) {

            InquiryOrder order = collect.stream().min((o1, o2) -> SHDateUtil.compareRangeTime(o1.getInquiryTime(), o2.getInquiryTime())).orElse(null);
            doctor.setSubscribeStartTime(order!=null?order.getInquiryTime():"");
            String rangeEndTime = SHDateUtil.getRangeEndTime(order.getInquiryTime());
            doctor.setSubscribeEndTime( rangeEndTime);
            doctor.setIsSubscribe(SHDateUtil.isAfterRangeTime(rangeEndTime)?2:1);
        }

        //将医生的字典字段处理下
        dictionaryService.resolveDoctorDictionFields(Lists.newArrayList(doctor));
        return doctor;
    }


    /**
     * 构建7天数据 对内部数据排序处理
     * @param list
     * @return
     */
    private List<DutiesDTO> buildAndSort(List<DoctorDuty> list) {
        List<DutiesDTO> sevenDuties = DutiesDTO.buildSevenDays();
        Map<String, List<DoctorDuty>> collect = list.stream().collect(Collectors.groupingBy(DoctorDuty::getDate));
        for (Map.Entry<String, List<DoctorDuty>> entry : collect.entrySet()) {
            //排序  08:00-08:30  09:00-09:30
            entry.getValue().sort((d1, d2) -> {
                String[] split01 = d1.getTimeRange().split("-");
                String[] split02 = d2.getTimeRange().split("-");
                String[] split1 = split01[0].split(":");
                String[] split2 = split02[0].split(":");
                int i;
                if ((i= Integer.valueOf(split1[0].replaceAll(" ","")).compareTo(Integer.valueOf(split2[0].replaceAll(" ",""))))!=0) {
                    return i;
                }
                return Integer.valueOf(split1[1].replaceAll(" ","")).compareTo(Integer.valueOf(split2[1].replaceAll(" ","")));
            });
        }
        for (Map.Entry<String, List<DoctorDuty>> entry : collect.entrySet()) {
            for (DutiesDTO dutiesDTO : sevenDuties) {
                if (entry.getKey().equals(dutiesDTO.getDbDate())) {
                    dutiesDTO.setList(entry.getValue());
                }
            }

        }
        return sevenDuties;
    }

}
